package com.shop.spring.utils;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class ImportExcelUtils {

    public static <T> List<T> convert2Vo(MultipartFile file, Class<T> clz) throws IOException {
        File temp = new File(Objects.requireNonNull(file.getOriginalFilename()));
        file.transferTo(temp);
        return convert2Vo(temp,clz);
    }

    public static <T> List<T> convert2Vo(File file, Class<T> clz) {
        List<T> result = new ArrayList<>();
        Workbook wb = null;
        try {
            if (file.getName().toLowerCase().endsWith(".xls")) {
                wb = new HSSFWorkbook(new FileInputStream(file));
            } else if (file.getName().toLowerCase().endsWith(".xlsx")) {
                wb = new XSSFWorkbook(new FileInputStream(file));
            } else {
                return null;
            }
            int numberOfSheets = wb.getNumberOfSheets(); //sheet 页数
            if (numberOfSheets < 1) {
                return null;
            }
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet firstSheet = wb.getSheetAt(i);
                int rowSize = firstSheet.getLastRowNum() + 1;
                for (int j = 1; j < rowSize; j++) { // 去除表头
                    Row row = firstSheet.getRow(j);
                    T bean = clz.newInstance();
                    Field[] declaredFields = clz.getDeclaredFields();
                    for (Field field : declaredFields) {
//                        boolean annotationPresent = field.isAnnotationPresent(ImportField.class);
//                        if (annotationPresent) {
//                            ImportField annotation = field.getAnnotation(ImportField.class);
                        //spring AnnotationUtils may be faster
                        ImportField annotation = AnnotationUtils.findAnnotation(field, ImportField.class);
                        if (annotation != null) {
                            field.setAccessible(true);
                            String simpleName = field.getType().getSimpleName().toLowerCase();
                            int order = annotation.order();
                            Cell cell = row.getCell(order);
                            if (cell != null) {
                                switch (simpleName) {
                                    case "string":
                                        cell.setCellType(CellType.STRING);
                                        field.set(bean, cell.getStringCellValue());
                                        break;
                                    case "integer":
                                    case "int":
                                        cell.setCellType(CellType.NUMERIC);
                                        field.set(bean, Double.valueOf(cell.getNumericCellValue()).intValue());
                                        break;
                                    case "double":
                                        cell.setCellType(CellType.NUMERIC);
                                        field.set(bean, cell.getNumericCellValue());
                                        break;
                                    case "date":
                                        String format = annotation.format();
                                        if (!StringUtils.isEmpty(format)) {
                                            cell.setCellType(CellType.STRING);
                                            field.set(bean, DateUtils.parseDate(cell.getStringCellValue(), format));
                                        }
                                        break;
                                }
                            }
                        }
                    }
                    result.add(bean);
                }
            }
        } catch (IOException | InstantiationException e) {
            System.err.println("read file or clz.newInstance error "+ e);
        } catch (IllegalAccessException e) {
            System.err.println("reflect set value error "+e);
        }
        return result;
    }

}
